#import <c.h>
#import <appkit/appkit.h>

#import "Thinker.h"

#import "WallPaperView.h"
#import "WallPaperWrap.h"

#define MODULE "WallPaper"

#define registerDefaults(d) (void) NXRegisterDefaults([NXApp appName], d)

#define getStringDefault(s) NXGetDefaultValue([NXApp appName], s)
#define writeStringDefault(s, v) NXWriteDefault([NXApp appName], s, v)

#define getFloatDefault(s) atof(getStringDefault(s))

#define STEPDEFAULTNAME "WallPaperStep"
#define STEP getFloatDefault(STEPDEFAULTNAME)

#define COUNTDEFAULTNAME "WallPaperCount"
#define COUNT getFloatDefault(COUNTDEFAULTNAME)

#define WILDDEFAULTNAME "WallPaperWildness"
#define WILD getFloatDefault(WILDDEFAULTNAME)

#define BRIGHTDEFAULTNAME "WallPaperBrightness"
#define BRIGHT getFloatDefault(BRIGHTDEFAULTNAME)

static NXDefaultsVector WallPaperDefaults = {
	{ STEPDEFAULTNAME, "0.1" },
	{ COUNTDEFAULTNAME, "4.0" },
	{ WILDDEFAULTNAME, "0.5" },
	{ BRIGHTDEFAULTNAME, "0.5" },
	{ NULL, NULL }
	};

@implementation WallPaperView

- initFrame:(NXRect *) frameRect
{
	[super initFrame:frameRect];

	registerDefaults(WallPaperDefaults);

	[NXApp getScreenSize:&size];

	size.height = (size.width /= COUNT);

	[(image = [[NXImage alloc] initSize:&size]) getSize:&size];

	inspector = nil;

	step = -1.0;
	
	loadwallpaper();

	return [self allocateGState];
}

- drawSelf:(const NXRect *) rects :(int) rectCount
{
	if (rects == NULL || rectCount == 0) return self;

	PSsetgray(NX_BLACK);

	NXRectFill(rects);

	step = -1.0;

	return self;
}

- free
{
	[image free];

	return [super free];
}

- tessellate
{
	float x, y, limit;
	int gState = [self gState];

	limit = bounds.size.width + bounds.origin.x;

	for(x = bounds.origin.x + size.width; x < limit; x += size.width)
		PScomposite(0.0, 0.0, size.width, size.height, gState, x, 0.0, NX_COPY);

	limit = bounds.size.height + bounds.origin.y;

	for(y = bounds.origin.y + size.height; y < limit; y += size.height)
		PScomposite(0.0, 0.0, bounds.size.width, size.height, gState, 0.0, y, NX_COPY);

	return self;
}

- oneStep
{
	float increment = STEP;
	static NXPoint point = { 0.0, 0.0 };

	if(step < increment) {
		[image lockFocus]; {
			wallpaper(WILD, size.width, BRIGHT);
			} [image unlockFocus];

		if(step < 0.0) {
			[image composite:NX_COPY toPoint:&point];
			step = 0.0;
			}
		else step = increment;
		}
	else {
		[image dissolve:(step * step) toPoint:&point];

		if((step += increment) > 1.0) step = 0.0;
		}

	return [self tessellate];
}

- inspector:sender
{
	char buffer[MAXPATHLEN];

	if (inspector == nil) {
		(void) sprintf(buffer,"%s/%s.nib", [sender moduleDirectory:MODULE], MODULE);
		[NXApp loadNibFile:buffer owner:self withNames:NO];
		}

	return inspector;
}

- (BOOL) useBufferedWindow { return YES; }

- (const char *) windowTitle { return MODULE; }

- setDefault:sender
{
	[sender setTag:YES];

	if([wildness tag]) {
		float wild = rint([wildness floatValue] * 2.0) / 2.0; /* coerce to 0.5 resolution */
		[wildness setFloatValue:wild];
		(void) writeStringDefault(WILDDEFAULTNAME, [wildness stringValue]);
		}

	if([brightness tag]) (void) writeStringDefault(BRIGHTDEFAULTNAME, [brightness stringValue]);

	[sender setTag:NO];

	return self;
}

- setWildness:anObject
{
	[(wildness = anObject) setFloatValue:WILD];

	return self;
}

- setBrightness:anObject
{
	[(brightness = anObject) setFloatValue:BRIGHT];

	return self;
}

@end
